package com.itheima.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hankcs.algorithm.AhoCorasickDoubleArrayTrie;
import com.itheima.admin.mapper.AdChannelMapper;
import com.itheima.admin.mapper.AdSensitiveMapper;
import com.itheima.admin.pojo.AdChannel;
import com.itheima.admin.pojo.AdSensitive;
import com.itheima.admin.service.WemediaNewsAutoScanSevice;
import com.itheima.article.dto.ArticleInfoDto;
import com.itheima.article.feign.ArticleApAuthorFeign;
import com.itheima.article.pojo.ApArticle;
import com.itheima.article.pojo.ApArticleConfig;
import com.itheima.article.pojo.ApArticleContent;
import com.itheima.common.constants.BusinessConstants;
import com.itheima.common.exception.LeadNewsException;
import com.itheima.common.util.ali.AliGreenScanner;
import com.itheima.common.vo.ResultVo;
import com.itheima.wemedia.dto.WmNewsContentNodeDto;
import com.itheima.wemedia.feign.DfsFeign;
import com.itheima.wemedia.feign.WmNewsFeign;
import com.itheima.wemedia.pojo.WmNews;
import com.itheima.wemedia.vo.WmNewsVo;
import com.xxl.job.core.log.XxlJobLogger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WemediaNewsAutoScanSeviceImpl implements WemediaNewsAutoScanSevice {


    @Autowired
    private WmNewsFeign wmNewsFeign;

    @Autowired
    private DfsFeign dfsFeign;

    @Autowired
    private ArticleApAuthorFeign articleApAuthorFeign;

    @Autowired
    private AliGreenScanner aliGreenScanner;

    @Autowired
    private AdSensitiveMapper adSensitiveMapper;

    @Autowired
    private AdChannelMapper adChannelMapper;





    /**
     * 审核文章
     *
     * @param newId
     * @param uuid
     */
    @Override
    public void autoScanWemediaNews(String newId, String uuid) {
        //1.远程调用文章微服务查询文章
        Long id = Long.valueOf(newId);
        ResultVo<WmNews> wmNewsResultVo = wmNewsFeign.getByWmNewsId(id);
        log.info("远程调用自媒体微服务查询文章信息 ：uuid{}，远程调用结果{}", uuid, wmNewsResultVo.isSuccess());
        //如果调用失败，直接return，并记录日志
        if (!wmNewsResultVo.isSuccess()) {
            //log.error("【出错】审核文章失败：uuid：{},文章id:{}，远程调用失败",uuid,newId);
            //return;
            throw new LeadNewsException("远程调用自媒体微服务查询文章信息失败");
        }
        //如果查询到的结果为null，直接return，并记录日志
        WmNews wmNews = wmNewsResultVo.getData();
        if (null == wmNews) {
            //log.error("【出错】审核文章失败：uuid：{},文章id:{}，远程调用的文章结果为空",uuid,newId);
            //return;
            throw new LeadNewsException("远程调用自媒体微服务查询文章信息失败");
        }
        //如果状态不等于1，直接return，并记录日志
        if (BusinessConstants.WmNewsConstants.STATUS_SUBMIT != wmNews.getStatus()) {
            //log.error("【出错】审核文章失败：uuid：{},文章id:{}，远程调用的文章的状态与审核状态不一致",uuid,newId);
            //return;
            throw new LeadNewsException("远程调用自媒体微服务查询文章的状态与审核状态不一致");
        }

        //2.获取文章的内容进行敏感词过滤
        //获取文章内容与标题拼接得到文本
        String text = getwmNewsContent(wmNews);
        //敏感词审核如果审核不通过，设置状态为2 ，并设置拒绝原因
        WmNews pojo = new WmNews();
        pojo.setId(wmNews.getId());
        Boolean result = SensitiveWordReview(text);
        if (result) {
            pojo.setStatus(BusinessConstants.WmNewsConstants.STATUS_FAIL);
            pojo.setReason("包含敏感词，审核失败");
            log.info("包含敏感词，审核失败: uuid{} ,id{}", uuid, newId);

        } else {
            //3.没有敏感词的话，调用阿里云进行文本反垃圾处理
            try {
                Map<String, String> Scan = aliGreenScanner.greenTextScan(text);
                if (BusinessConstants.ScanConstants.PASS.equals(Scan.get("suggestion"))||BusinessConstants.ScanConstants.NORMAL.equals(Scan.get("suggestion"))) {
                    //如果文本没有垃圾就获取图片，对图片进行反垃圾处理
                    //获取图片地址
                    List<String> images = getWmNewsImages(wmNews);
                    if (CollectionUtils.isNotEmpty(images)) {
                        //通过远程调用dfs下载图片、
                        ResultVo<List<byte[]>> listResultVo = dfsFeign.download(images);
                        if (!listResultVo.isSuccess()) {
                            //log.error("【出错】审核文章图片失败：uuid：{},文章id:{}，远程调用失败", uuid, newId);
                            //return;
                            throw new LeadNewsException("调用dfs微服务下载图片失败");
                        }
                        List<byte[]> imageBytes = listResultVo.getData();
                        if (CollectionUtils.isEmpty(imageBytes)) {
                            log.error("【出错】审核文章图片失败：uuid：{},文章id:{}，远程调用的图片结果为空", uuid, newId);
                            return;
                        }

                        try {
                            //调用阿里云的图片反垃圾处理
                             Scan = aliGreenScanner.imageScan(imageBytes);
                            //if (BusinessConstants.ScanConstants.PASS.equals(Scan.get("suggestion"))||BusinessConstants.ScanConstants.NORMAL.equals(Scan.get("suggestion"))) {
                            //
                            //    //如果没有垃圾图片，需要修改文章的状态,变成审核通过
                            //    pojo.setStatus(BusinessConstants.WmNewsConstants.STATUS_PASS);
                            //
                            //}
                        } catch (Exception e) {
                            pojo.setStatus(BusinessConstants.WmNewsConstants.STATUS_MANUAL);
                            pojo.setReason("调用阿里云图片反垃圾失败，需要人工审核");
                            log.error("【出错】审核文章失败：uuid：{},文章id:{}，调用阿里云图片反垃圾失败", uuid, newId);

                        }
                    }
                }
                //对于文章处理进行统一处理
                String suggestion = Scan.get("suggestion");
                if (null ==suggestion){
                    log.error("【出错】自动审核文章失败：uuid：{},文章id:{}", uuid, newId);
                }
                switch (suggestion){
                    case BusinessConstants.ScanConstants.PASS:
                        pojo.setStatus(BusinessConstants.WmNewsConstants.STATUS_PASS);
                        break;
                    case BusinessConstants.ScanConstants.NORMAL:
                        pojo.setStatus(BusinessConstants.WmNewsConstants.STATUS_PASS);
                        break;
                    case BusinessConstants.ScanConstants.REVIEW:
                        pojo.setStatus(BusinessConstants.WmNewsConstants.STATUS_MANUAL);
                        break;
                    case BusinessConstants.ScanConstants.BLOCK:
                        pojo.setStatus(BusinessConstants.WmNewsConstants.STATUS_FAIL);
                        pojo.setReason(Scan.get("label"));
                        break;
                    default:
                        log.error("【出错】自动审核文章失败：uuid：{},文章id:{}", uuid, newId);
                        break;
                }

            } catch (Exception e) {
                pojo.setStatus(BusinessConstants.WmNewsConstants.STATUS_MANUAL);
                pojo.setReason("调用阿里云文本反垃圾失败，需要人工审核");
                log.error("【出错】审核文章失败：uuid：{},文章id:{}，调用阿里云文本反垃圾失败", uuid, newId);

            }
        }
        ResultVo updateResult = wmNewsFeign.update(pojo);
        if (!updateResult.isSuccess()) {
            throw new LeadNewsException("远程调用自媒体微服务修改文章信息失败");
        }
    }



    /**
     * 获取图片地址
     *
     * @param wmNews
     * @return
     */
    private List<String> getWmNewsImages(WmNews wmNews) {
        //获取文章内容中的图片
        List<WmNewsContentNodeDto> contentList = JSON.parseArray(wmNews.getContent(), WmNewsContentNodeDto.class);
        List<String> imageList = contentList.stream().filter(node -> BusinessConstants.WmNewsConstants.CONTENT_IMAGE.equals(node.getType()))
                .map(WmNewsContentNodeDto::getValue).collect(Collectors.toList());
        //获取封面的主题，并判断添加
        if (StringUtils.isNotEmpty(wmNews.getImages())) {
            String[] images = wmNews.getImages().split(",");
            Collections.addAll(imageList, images);
        }
        //去重一样的图片
        imageList =imageList.stream().distinct().collect(Collectors.toList());
        return imageList;
    }

    /**
     * 敏感词操作
     *
     * @param text
     * @return
     */
    private Boolean SensitiveWordReview(String text) {

        //查询敏感词表(只查询sensitives字段)
        QueryWrapper<AdSensitive> wrapper = new QueryWrapper<>();
        wrapper.select("sensitives");
        List<AdSensitive> sensitives = adSensitiveMapper.selectList(wrapper);
        //没有敏感词
        if (null == sensitives) {
            return false;
        }
        //有敏感词
        //构建敏感词树map
        Map<String, String> map = sensitives.stream().filter(n -> !"".equals(n.getSensitives())).collect(Collectors.toMap(AdSensitive::getSensitives, AdSensitive::getSensitives));
        //构建字典
        AhoCorasickDoubleArrayTrie<String> acdat = new AhoCorasickDoubleArrayTrie<String>();
        acdat.build(map);
        //查询
        AhoCorasickDoubleArrayTrie.Hit<String> first = acdat.findFirst(text);
        //返回结果

        return first != null;
    }

    /**
     * 获取文本和标题组成字符串
     *
     * @param wmNews
     * @return
     */
    private String getwmNewsContent(WmNews wmNews) {
        String content = wmNews.getContent();
        if (StringUtils.isEmpty(content)) {
            throw new LeadNewsException("文章内容不存在");
        }
        List<WmNewsContentNodeDto> contentNodeDtoList = JSON.parseArray(content, WmNewsContentNodeDto.class);
        List<String> textList = contentNodeDtoList.stream()
                .filter(n -> BusinessConstants.WmNewsConstants.CONTENT_TEXT.equals(n.getType()))
                .map(WmNewsContentNodeDto::getValue).collect(Collectors.toList());
        textList.add(wmNews.getTitle());
        String text = String.join(",", textList);
        return text;
    }


    /**
     * 同步文章到文章微服务中的文章表中
     *
     * @param wmNewsVo
     * @return
     */
    @Override
    public Boolean syncArticleTask(WmNewsVo wmNewsVo) {
        ArticleInfoDto dto = new ArticleInfoDto();
        //1.构建文章表数据ApArticle
        ApArticle apArticle=buildapArticle(wmNewsVo);
        dto.setApArticle(apArticle);
        //2.构建文章内容表数据ApArticleContent
        ApArticleContent apArticleContent =buildApArticleContent(wmNewsVo);
        dto.setApArticleContent(apArticleContent);
        //3.构建文章配置表数据ApArticleConfig
        ApArticleConfig apArticleConfig =buildApArticleConfig(wmNewsVo);
        dto.setApArticleConfig(apArticleConfig);
        //4.设置appUserId
        dto.setApUserId(wmNewsVo.getUserId());
        //5.设置自媒体用户id  wmUserId
        dto.setWmUserId(wmNewsVo.getApUserId());
        //6.设置自媒体文章id
        dto.setWmNewsId(wmNewsVo.getId());

        //7.远程调用文章微服务保存文章信息

        ResultVo saveArticleInfoResult = articleApAuthorFeign.saveArticleInfo(dto);
        if (!saveArticleInfoResult.isSuccess()){
            log.error("远程调用文章微服务保存文章信息失败！");
            XxlJobLogger.log("远程调用文章微服务保存文章信息失败！");
            return false;
        }
        //8. 解析返回结果
        return true;
    }





    /**
     * 构建文章表数据ApArticle
     * @param wmNewsVo
     * @return
     */
    private ApArticle buildapArticle(WmNewsVo wmNewsVo) {

        ApArticle apArticle = new ApArticle();
        BeanUtils.copyProperties(wmNewsVo,apArticle);
        //设置wmNewsVo 未拥有的数据
        apArticle.setId(wmNewsVo.getArticleId());
        //设置作者id和作者名称
        apArticle.setAuthorId(wmNewsVo.getApUserId());
        apArticle.setAuthorName(wmNewsVo.getAuthorName());
        //设置频道名称
        Integer channelId = wmNewsVo.getChannelId();
        AdChannel adChannel = adChannelMapper.selectById(channelId);
        if (null==adChannel){
            throw new LeadNewsException("文章频道不存在");
        }
        apArticle.setChannelName(adChannel.getName());
        //设置文章布局
        apArticle.setLayout(wmNewsVo.getType());
        apArticle.setFlag(BusinessConstants.ArticleConstants.FLAG_NORMAL);
        apArticle.setLikes(0);
        apArticle.setCollection(0);
        apArticle.setComment(0);
        apArticle.setViews(0);
        apArticle.setOrigin(BusinessConstants.ArticleConstants.ORIGIN_WEMEDIA);
        return apArticle;

    }

    /**
     * 构建文章内容表数据ApArticleContent
     * @param wmNewsVo
     * @return
     */
    private ApArticleContent buildApArticleContent(WmNewsVo wmNewsVo) {

        ApArticleContent apArticleContent = new ApArticleContent();
        apArticleContent.setContent(wmNewsVo.getContent());
        return apArticleContent;
    }

    /**
     * 构建文章配置表数据ApArticleConfig
     * @param wmNewsVo
     * @return
     */
    private ApArticleConfig buildApArticleConfig(WmNewsVo wmNewsVo) {
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setIsComment(BusinessConstants.ArticleConfig.IS_COMMENT_YES);
        apArticleConfig.setIsForward(BusinessConstants.ArticleConfig.IS_FORWARD_YES);
        apArticleConfig.setIsDown(BusinessConstants.ArticleConfig.IS_DOWN_NO);
        apArticleConfig.setIsDelete(BusinessConstants.ArticleConfig.IS_DELETE_NO);
        return apArticleConfig;
    }
}
